<template>
  <div class="full" v-loading="loading" element-loading-text="用例拼命运行中，请稍等..."
       element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.6)">
    <div>
      <!--面包屑-->
      <el-breadcrumb separator-class="el-icon-arrow-right">
        <el-breadcrumb-item>接口测试</el-breadcrumb-item>
        <el-breadcrumb-item>用例管理</el-breadcrumb-item>
      </el-breadcrumb>
      <!--卡片-->
      <el-card class="box-card">
        <el-row :gutter="10" style="padding-left: 0">
          <!--搜索框-->
          <el-col :span="6">
            <el-input placeholder="请输入用例名称" v-model="queryParams.name" clearable @clear="getTestCaseList" @keyup.enter.native="getTestCaseList">
              <el-button slot="append" icon="el-icon-search" @click="getTestCaseList" class="search"></el-button>
            </el-input>
          </el-col>
          <!--创建按钮-->
          <el-col :span="4">
            <el-button type="primary" @click="openAddTestCaseDialog" plain>创建用例</el-button>
          </el-col>
        </el-row>
        <!--表格-->
        <el-table :data="testcaseList" :cell-style="cellStyle" border stripe>
          <el-table-column label="#" type="index"></el-table-column>
          <el-table-column label="用例名称" prop="name"></el-table-column>
          <el-table-column label="所属接口" prop="interface"></el-table-column>
          <el-table-column label="所属项目" prop="project"></el-table-column>
          <el-table-column label="创建时间" prop="create_time"></el-table-column>
          <el-table-column label="操作" min-width="130px">
            <template slot-scope="scope">
              <el-button type="primary" size="mini" @click="openRunTestCaseDialog(scope.row)" plain>运 行</el-button>
              <el-button type="warning" size="mini" @click="openEditTestCaseDialog(scope.row)" plain>编 辑</el-button>
              <el-button type="danger" size="mini" @click="deleteThisTestCase(scope.row.id)" plain>删 除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <!--分页-->
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="queryParams.p"
          :page-sizes="[5, 10, 20, 40]"
          :page-size="queryParams.s"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total">
        </el-pagination>
      </el-card>
      <!--新建用例对话框-->
      <el-dialog title="创建用例" :visible.sync="addTestCaseDialogVisible" width="56%" :append-to-body="true"
                 :close-on-click-modal="false" :close-on-press-escape="false" @close="addDialogClose">
        <!--用例表单-->
        <el-form :model="addTestCaseForm" status-icon :rules="addTestCaseRule" ref="addTestCaseRef" label-width="90px">
          <el-form-item label="所属项目" prop="project_id">
            <el-select v-model="addTestCaseForm.project_id" placeholder="请选择所属项目"  @change="addProjectChange">
              <el-option
                v-for="project in projectAndInterfaceNames"
                :key="project.id"
                :label="project.name"
                :value="project.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="所属接口" prop="interface_id">
            <el-select v-model="addTestCaseForm.interface_id" placeholder="请选择所属接口">
              <el-option
                v-for="interface1 in interfaceNames"
                :key="interface1.id"
                :label="interface1.name"
                :value="interface1.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="用例名称" prop="name">
            <el-input v-model="addTestCaseForm.name" placeholder="请输入用例名称"></el-input>
          </el-form-item>
          <!--标签栏-->
          <el-tabs v-model="mainActiveName" @tab-click="handleTabPage">
            <el-tab-pane label="前置用例" name="first">
              <el-row style="margin-top: 0">
                项目
                <el-select v-model="setupProjectAndInterface.project_id" placeholder="请选择项目"  @change="addSetupProjectChange" size="mini">
                  <el-option
                    v-for="project in setupProjectAndInterfaceNames"
                    :key="project.id"
                    :label="project.name"
                    :value="project.id">
                  </el-option>
                </el-select>
              </el-row>
              <el-row>
                接口
                <el-select v-model="setupProjectAndInterface.interface_id" placeholder="请选择接口"  @change="addSetupInterfaceChange" size="mini">
                  <el-option
                    v-for="interface1 in setupInterfaceNames"
                    :key="interface1.id"
                    :label="interface1.name"
                    :value="interface1.id">
                  </el-option>
                </el-select>
              </el-row>
              <el-row>
                <el-transfer v-model="choiceCase"
                             :data="allCase"
                             :titles="['待选用例', '已选用例']"
                             :target-order="'push'"
                             :props="{key: 'id', label: 'name'}"
                             @change="rightChoiceCaseChange"
                             :right-default-checked="rightChoiceCase">
                </el-transfer>
              </el-row>
            </el-tab-pane>
            <el-tab-pane label="请求主体" name="second">
              <el-row style="margin-top: 0">
                公共配置
                <el-cascader v-model="choiceConfig"
                             :options="configOptions"
                             :props="{value: 'id', label: 'name', children: 'config'}"
                             size="mini"
                             style="width: 50%"
                             placeholder="请选择公共配置"
                             clearable></el-cascader>
              </el-row>
              <el-row>
                请求方法
                <el-select v-model="requestMethod"
                           placeholder="请选择请求方法"
                           size="mini"
                           style="width: 135px">
                  <el-option
                    v-for="item in requestMethods"
                    :key="item.value"
                    :label="item.label"
                    :value="item.label">
                  </el-option>
                </el-select>
              </el-row>
              <el-row>
                请求路径
                <el-input placeholder="请输入请求路径 ( 例 : /api/testcase/ )"
                          v-model="requestUrl" size="mini" style="width: 50%" clearable>
                </el-input>
              </el-row>
              <el-tabs v-model="requestBodyName" :tab-position="'left'">
                <el-tab-pane label="局部变量" name="one">
                  <el-row :gutter="10" v-for="(variable, index) in variableList" :key="index">
                    <el-col :span="6">
                      <el-input v-model="variable.key" placeholder="key" size="mini"></el-input>
                    </el-col>
                    <el-col :span="3">
                      <el-select v-model="variable.type" placeholder="type" size="mini">
                        <el-option
                          v-for="item in dataType"
                          :key="item.value"
                          :label="item.label"
                          :value="item.label">
                        </el-option>
                      </el-select>
                    </el-col>
                    <el-col :span="13">
                      <el-input v-model="variable.value" placeholder="value" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteVariable(variable)" icon="el-icon-delete" size="mini" style="margin-top: 0"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addVariable" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                  </el-row>
                </el-tab-pane>
                <el-tab-pane label="请求头" name="two">
                  <el-row :gutter="10" v-for="(header, index) in headerList" :key="index">
                    <el-col :span="8">
                      <el-input v-model="header.key" placeholder="key" size="mini"></el-input>
                    </el-col>
                    <el-col :span="14">
                      <el-input v-model="header.value" placeholder="value" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteHeader(header)" icon="el-icon-delete" size="mini" style="margin-top: 0"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addHeader" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                  </el-row>
                </el-tab-pane>
                <el-tab-pane label="请求参数" name="three">
                  <el-tabs v-model="activeName" @tab-click="handleTabPage" style="margin-top: 0; padding-left: 20px">
                    <el-tab-pane label="params" name="one">
                      <el-row :gutter="10" v-for="(params, index) in paramsList" :key="index" style="padding-left: 0">
                        <el-col :span="6">
                          <el-input v-model="params.key" placeholder="key" size="mini"></el-input>
                        </el-col>
                        <el-col :span="3">
                          <el-select v-model="params.type" placeholder="type" size="mini">
                            <el-option
                              v-for="item in dataType"
                              :key="item.value"
                              :label="item.label"
                              :value="item.label">
                            </el-option>
                          </el-select>
                        </el-col>
                        <el-col :span="13">
                          <el-input v-model="params.value" placeholder="value" size="mini"></el-input>
                        </el-col>
                        <el-col :span="2">
                          <el-button @click="deleteParams(params)" icon="el-icon-delete" size="mini" style="margin-top: 0"></el-button>
                        </el-col>
                      </el-row>
                      <el-row style="padding-left: 0; text-align: right">
                        <el-button @click="addParams" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                      </el-row>
                    </el-tab-pane>
                    <el-tab-pane label="form-data" name="two">
                      <el-row :gutter="10" v-for="(formData, index) in formDataList" :key="index" style="padding-left: 0">
                        <el-col :span="6">
                          <el-input v-model="formData.key" placeholder="key" size="mini"></el-input>
                        </el-col>
                        <el-col :span="3">
                          <el-select v-model="formData.type" placeholder="type" size="mini">
                            <el-option
                              v-for="item in dataType"
                              :key="item.value"
                              :label="item.label"
                              :value="item.label">
                            </el-option>
                          </el-select>
                        </el-col>
                        <el-col :span="13">
                          <el-input v-model="formData.value" placeholder="value or $var_name" size="mini"></el-input>
                        </el-col>
                        <el-col :span="2">
                          <el-button @click="deleteFormData(formData)" icon="el-icon-delete" size="mini" style="margin-top: 0"></el-button>
                        </el-col>
                      </el-row>
                      <el-row style="padding-left: 0; text-align: right">
                        <el-button @click="addFormData" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                      </el-row>
                    </el-tab-pane>
                    <el-tab-pane label="json" name="three">
                      <editor ref="jsonDataRef" v-model="jsonAddData" @init="jsonDataInit" lang="json" theme="chrome"
                              style="width: 95%; height: 200px; border: rgb(136 136 136) solid 1px" :options="{
                       tabSize:2,
                       fontSize:14,
                       showPrintMargin:false,
                       enableSnippets: true,
                       enableLiveAutocompletion: true,
                       enableBasicAutocompletion: true
                     }"></editor>
                    </el-tab-pane>
                  </el-tabs>
                </el-tab-pane>
                <el-tab-pane label="参数化" name="four">
                  <el-row :gutter="10" v-for="(parameters, index) in parametersList" :key="index">
                    <el-col :span="7">
                      <el-input v-model="parameters.key" placeholder="k or k1-k2" size="mini"></el-input>
                    </el-col>
                    <el-col :span="15">
                      <el-input v-model="parameters.value" placeholder="['v1','v2'] or [['v1','v2'],['v3','v4']] or ${func(p1,p2,...)}" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteParameters(parameters)" icon="el-icon-delete" size="mini"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addParameters" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                  </el-row>
                </el-tab-pane>
              </el-tabs>
            </el-tab-pane>
            <el-tab-pane label="后置处理" name="third">
              <el-tabs v-model="backName" :tab-position="'left'" style="margin-top: 0">
                <el-tab-pane label="响应提取" name="one">
                  <el-row :gutter="10" v-for="(extract, index) in extractList" :key="index">
                    <el-col :span="8">
                      <el-input v-model="extract.key" placeholder="key" size="mini"></el-input>
                    </el-col>
                    <el-col :span="14">
                      <el-input v-model="extract.value" placeholder="value" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteExtract(extract)" icon="el-icon-delete" size="mini"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addExtract" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                  </el-row>
                </el-tab-pane>
                <el-tab-pane label="响应断言" name="two">
                  <el-row :gutter="10" v-for="(assert, index) in assertList" :key="index">
                    <el-col :span="5">
                      <el-input v-model="assert.key" placeholder="key" size="mini"></el-input>
                    </el-col>
                    <el-col :span="4">
                      <el-select v-model="assert.method" placeholder="method" size="mini">
                        <el-option
                          v-for="item in assertType"
                          :key="item.value"
                          :label="item.label"
                          :value="item.label">
                        </el-option>
                      </el-select>
                    </el-col>
                    <el-col :span="3">
                      <el-select v-model="assert.type" placeholder="type" size="mini">
                        <el-option
                          v-for="item in dataType"
                          :key="item.value"
                          :label="item.label"
                          :value="item.label">
                        </el-option>
                      </el-select>
                    </el-col>
                    <el-col :span="10">
                      <el-input v-model="assert.value" placeholder="value" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteAssert(assert)" icon="el-icon-delete" size="mini"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addAssert" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                  </el-row>
                </el-tab-pane>
              </el-tabs>
            </el-tab-pane>
            <el-tab-pane label="其他配置" name="fourth">
              <el-tabs v-model="otherName" :tab-position="'left'" style="margin-top: 0">
                <el-tab-pane label="setup_hooks" name="one">
                  <el-row :gutter="10" v-for="(setupHook, index) in setupHooksList" :key="index">
                    <el-col :span="22">
                      <el-input v-model="setupHook.key" placeholder="key" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteSetupHook(setupHook)" icon="el-icon-delete" size="mini"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addSetupHook" icon="el-icon-plus" size="mini"></el-button>
                  </el-row>
                </el-tab-pane>
                <el-tab-pane label="teardown_hooks" name="two">
                  <el-row :gutter="10" v-for="(teardownHook, index) in teardownHooksList" :key="index">
                    <el-col :span="22">
                      <el-input v-model="teardownHook.key" placeholder="key" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteTeardownHook(teardownHook)" icon="el-icon-delete" size="mini"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addTeardownHook" icon="el-icon-plus" size="mini"></el-button>
                  </el-row>
                </el-tab-pane>
              </el-tabs>
            </el-tab-pane>
          </el-tabs>
        </el-form>
        <span slot="footer" class="dialog-footer">
        <el-button @click="addTestCaseDialogClose">取 消</el-button>
        <el-button type="primary" @click="addTestCase">确 定</el-button>
      </span>
      </el-dialog>
      <!--编辑用例对话框-->
      <el-dialog title="编辑用例" :visible.sync="editTestCaseDialogVisible" width="56%" :append-to-body="true"
                 :close-on-click-modal="false" :close-on-press-escape="false" @close="editDialogClose">
        <!--用例表单-->
        <el-form :model="editTestCaseForm" status-icon :rules="editTestCaseRule" ref="editTestCaseRef" label-width="90px">
          <el-form-item label="所属项目" prop="project_id">
            <el-select v-model="editTestCaseForm.project_id" placeholder="请选择所属项目"  @change="editProjectChange">
              <el-option
                v-for="project in projectAndInterfaceNames"
                :key="project.id"
                :label="project.name"
                :value="project.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="所属接口" prop="interface_id">
            <el-select v-model="editTestCaseForm.interface_id" placeholder="请选择所属接口">
              <el-option
                v-for="interface1 in interfaceNames"
                :key="interface1.id"
                :label="interface1.name"
                :value="interface1.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="用例名称" prop="name">
            <el-input v-model="editTestCaseForm.name" placeholder="请输入用例名称"></el-input>
          </el-form-item>
          <!--标签栏-->
          <el-tabs v-model="mainActiveName" @tab-click="handleTabPage">
            <el-tab-pane label="前置用例" name="first">
              <el-row style="margin-top: 0">
                项目
                <el-select v-model="setupProjectAndInterface.project_id" placeholder="请选择项目"  @change="editSetupProjectChange" size="mini">
                  <el-option
                    v-for="project in setupProjectAndInterfaceNames"
                    :key="project.id"
                    :label="project.name"
                    :value="project.id">
                  </el-option>
                </el-select>
              </el-row>
              <el-row>
                接口
                <el-select v-model="setupProjectAndInterface.interface_id" placeholder="请选择接口"  @change="editSetupInterfaceChange" size="mini">
                  <el-option
                    v-for="interface1 in setupInterfaceNames"
                    :key="interface1.id"
                    :label="interface1.name"
                    :value="interface1.id">
                  </el-option>
                </el-select>
              </el-row>
              <el-row>
                <el-transfer v-model="choiceCase"
                             :data="allCase"
                             :titles="['待选用例', '已选用例']"
                             :target-order="'push'"
                             :props="{key: 'id', label: 'name'}"
                             @change="rightChoiceCaseChange"
                             :right-default-checked="rightChoiceCase">
                </el-transfer>
              </el-row>
            </el-tab-pane>
            <el-tab-pane label="请求主体" name="second">
              <el-row style="margin-top: 0">
                公共配置
                <el-cascader v-model="choiceConfig"
                             :options="configOptions"
                             :props="{value: 'id', label: 'name', children: 'config'}"
                             size="mini"
                             style="width: 50%"
                             placeholder="请选择公共配置"
                             clearable></el-cascader>
              </el-row>
              <el-row>
                请求方法
                <el-select v-model="requestMethod"
                           placeholder="请选择请求方法"
                           size="mini"
                           style="width: 135px">
                  <el-option
                    v-for="item in requestMethods"
                    :key="item.value"
                    :label="item.label"
                    :value="item.label">
                  </el-option>
                </el-select>
              </el-row>
              <el-row>
                请求路径
                <el-input placeholder="请输入请求路径 ( 例 : /api/testcase/ )"
                          v-model="requestUrl" size="mini" style="width: 50%" clearable>
                </el-input>
              </el-row>
              <el-tabs v-model="requestBodyName" :tab-position="'left'">
                <el-tab-pane label="局部变量" name="one">
                  <el-row :gutter="10" v-for="(variable, index) in variableList" :key="index">
                    <el-col :span="6">
                      <el-input v-model="variable.key" placeholder="key" size="mini"></el-input>
                    </el-col>
                    <el-col :span="3">
                      <el-select v-model="variable.type" placeholder="type" size="mini">
                        <el-option
                          v-for="item in dataType"
                          :key="item.value"
                          :label="item.label"
                          :value="item.label">
                        </el-option>
                      </el-select>
                    </el-col>
                    <el-col :span="13">
                      <el-input v-model="variable.value" placeholder="value" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteVariable(variable)" icon="el-icon-delete" size="mini" style="margin-top: 0"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addVariable" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                  </el-row>
                </el-tab-pane>
                <el-tab-pane label="请求头" name="two">
                  <el-row :gutter="10" v-for="(header, index) in headerList" :key="index">
                    <el-col :span="8">
                      <el-input v-model="header.key" placeholder="key" size="mini"></el-input>
                    </el-col>
                    <el-col :span="14">
                      <el-input v-model="header.value" placeholder="value" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteHeader(header)" icon="el-icon-delete" size="mini" style="margin-top: 0"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addHeader" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                  </el-row>
                </el-tab-pane>
                <el-tab-pane label="请求参数" name="three">
                  <el-tabs v-model="activeName" @tab-click="handleTabPage" style="margin-top: 0; padding-left: 20px">
                    <el-tab-pane label="params" name="one">
                      <el-row :gutter="10" v-for="(params, index) in paramsList" :key="index" style="padding-left: 0">
                        <el-col :span="6">
                          <el-input v-model="params.key" placeholder="key" size="mini"></el-input>
                        </el-col>
                        <el-col :span="3">
                          <el-select v-model="params.type" placeholder="type" size="mini">
                            <el-option
                              v-for="item in dataType"
                              :key="item.value"
                              :label="item.label"
                              :value="item.label">
                            </el-option>
                          </el-select>
                        </el-col>
                        <el-col :span="13">
                          <el-input v-model="params.value" placeholder="value" size="mini"></el-input>
                        </el-col>
                        <el-col :span="2">
                          <el-button @click="deleteParams(params)" icon="el-icon-delete" size="mini" style="margin-top: 0"></el-button>
                        </el-col>
                      </el-row>
                      <el-row style="padding-left: 0; text-align: right">
                        <el-button @click="addParams" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                      </el-row>
                    </el-tab-pane>
                    <el-tab-pane label="form-data" name="two">
                      <el-row :gutter="10" v-for="(formData, index) in formDataList" :key="index" style="padding-left: 0">
                        <el-col :span="6">
                          <el-input v-model="formData.key" placeholder="key" size="mini"></el-input>
                        </el-col>
                        <el-col :span="3">
                          <el-select v-model="formData.type" placeholder="type" size="mini">
                            <el-option
                              v-for="item in dataType"
                              :key="item.value"
                              :label="item.label"
                              :value="item.label">
                            </el-option>
                          </el-select>
                        </el-col>
                        <el-col :span="13">
                          <el-input v-model="formData.value" placeholder="value or $var_name" size="mini"></el-input>
                        </el-col>
                        <el-col :span="2">
                          <el-button @click="deleteFormData(formData)" icon="el-icon-delete" size="mini" style="margin-top: 0"></el-button>
                        </el-col>
                      </el-row>
                      <el-row style="padding-left: 0; text-align: right">
                        <el-button @click="addFormData" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                      </el-row>
                    </el-tab-pane>
                    <el-tab-pane label="json" name="three">
                      <editor ref="jsonDataRef" v-model="jsonEditData" @init="jsonDataInit" lang="json" theme="chrome"
                              style="width: 95%; height: 200px; border: rgb(136 136 136) solid 1px" :options="{
                       tabSize:2,
                       fontSize:14,
                       showPrintMargin:false,
                       enableSnippets: true,
                       enableLiveAutocompletion: true,
                       enableBasicAutocompletion: true
                     }"></editor>
                    </el-tab-pane>
                  </el-tabs>
                </el-tab-pane>
                <el-tab-pane label="参数化" name="four">
                  <el-row :gutter="10" v-for="(parameters, index) in parametersList" :key="index">
                    <el-col :span="7">
                      <el-input v-model="parameters.key" placeholder="k or k1-k2" size="mini"></el-input>
                    </el-col>
                    <el-col :span="15">
                      <el-input v-model="parameters.value" placeholder="['v1','v2'] or [['v1','v2'],['v3','v4']] or ${func(p1,p2,...)}" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteParameters(parameters)" icon="el-icon-delete" size="mini"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addParameters" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                  </el-row>
                </el-tab-pane>
              </el-tabs>
            </el-tab-pane>
            <el-tab-pane label="后置处理" name="third">
              <el-tabs v-model="backName" :tab-position="'left'" style="margin-top: 0">
                <el-tab-pane label="响应提取" name="one">
                  <el-row :gutter="10" v-for="(extract, index) in extractList" :key="index">
                    <el-col :span="8">
                      <el-input v-model="extract.key" placeholder="key" size="mini"></el-input>
                    </el-col>
                    <el-col :span="14">
                      <el-input v-model="extract.value" placeholder="value" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteExtract(extract)" icon="el-icon-delete" size="mini"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addExtract" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                  </el-row>
                </el-tab-pane>
                <el-tab-pane label="响应断言" name="two">
                  <el-row :gutter="10" v-for="(assert, index) in assertList" :key="index">
                    <el-col :span="5">
                      <el-input v-model="assert.key" placeholder="key" size="mini"></el-input>
                    </el-col>
                    <el-col :span="4">
                      <el-select v-model="assert.method" placeholder="method" size="mini">
                        <el-option
                          v-for="item in assertType"
                          :key="item.value"
                          :label="item.label"
                          :value="item.label">
                        </el-option>
                      </el-select>
                    </el-col>
                    <el-col :span="3">
                      <el-select v-model="assert.type" placeholder="type" size="mini">
                        <el-option
                          v-for="item in dataType"
                          :key="item.value"
                          :label="item.label"
                          :value="item.label">
                        </el-option>
                      </el-select>
                    </el-col>
                    <el-col :span="10">
                      <el-input v-model="assert.value" placeholder="value" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteAssert(assert)" icon="el-icon-delete" size="mini"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addAssert" icon="el-icon-plus" size="mini" style="margin-right: 4px"></el-button>
                  </el-row>
                </el-tab-pane>
              </el-tabs>
            </el-tab-pane>
            <el-tab-pane label="其他配置" name="fourth">
              <el-tabs v-model="otherName" :tab-position="'left'" style="margin-top: 0">
                <el-tab-pane label="setup_hooks" name="one">
                  <el-row :gutter="10" v-for="(setupHook, index) in setupHooksList" :key="index">
                    <el-col :span="22">
                      <el-input v-model="setupHook.key" placeholder="key" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteSetupHook(setupHook)" icon="el-icon-delete" size="mini"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addSetupHook" icon="el-icon-plus" size="mini"></el-button>
                  </el-row>
                </el-tab-pane>
                <el-tab-pane label="teardown_hooks" name="two">
                  <el-row :gutter="10" v-for="(teardownHook, index) in teardownHooksList" :key="index">
                    <el-col :span="22">
                      <el-input v-model="teardownHook.key" placeholder="key" size="mini"></el-input>
                    </el-col>
                    <el-col :span="2">
                      <el-button @click="deleteTeardownHook(teardownHook)" icon="el-icon-delete" size="mini"></el-button>
                    </el-col>
                  </el-row>
                  <el-row style="padding-left: 0; text-align: right">
                    <el-button @click="addTeardownHook" icon="el-icon-plus" size="mini"></el-button>
                  </el-row>
                </el-tab-pane>
              </el-tabs>
            </el-tab-pane>
          </el-tabs>
        </el-form>
        <span slot="footer" class="dialog-footer">
        <el-button @click="editTestCaseDialogClose">取 消</el-button>
        <el-button type="primary" @click="editTestCase">确 定</el-button>
      </span>
      </el-dialog>
      <!--运行用例对话框-->
      <el-dialog title="运行用例" :visible.sync="runTestCaseDialogVisible" width="20%" :append-to-body="true"
                 :close-on-click-modal="false" :close-on-press-escape="false" @close="runDialogClose">
        <el-form :model="runTestCaseForm" status-icon :rules="runTestCaseRule" ref="runTestCaseRef" label-width="90px">
          <el-form-item label="运行环境" prop="env_id">
            <el-select v-model="runTestCaseForm.env_id" placeholder="请选择运行环境">
              <el-option
                v-for="env in environmentList"
                :key="env.id"
                :label="env.name"
                :value="env.id">
              </el-option>
            </el-select>
          </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
        <el-button @click="runTestCaseDialogClose">取 消</el-button>
        <el-button type="primary" @click="runThisTestCase">开 始</el-button>
      </span>
      </el-dialog>
    </div>
  </div>
</template>

<script>
import {
  getTestCases,
  createTestCase,
  editTestCase,
  deleteTestCase,
  runTestCase,
  getEnvironmentNames,
  getProjectAndInterfaceNames,
  getProjectAndInterfaceAndConfigNames
} from '../../api/api'
import Editor from 'vue2-ace-editor'

export default {
  components: {
    Editor
  },
  created () {
    this.getTestCaseList()
    this.getProjectAndInterfaceNameList()
    this.getProjectAndInterfaceAndConfigNames()
  },
  data () {
    return {
      loading: false,
      runTestCaseForm: {
        env_id: ''
      },
      tmpName: '',
      addTestCaseForm: {
        project_id: '',
        interface_id: '',
        name: '',
        config: null,
        fixture: [],
        content: {
          request: {
            url: '',
            method: '',
            headers: {},
            json: {},
            data: [],
            params: []
          },
          parameters: {},
          variables: [],
          extract: [],
          validate: [],
          setupHooks: [],
          teardownHooks: []
        }
      },
      editTestCaseForm: {},
      setupProjectAndInterface: {
        project_id: '',
        interface_id: ''
      },
      queryParams: {
        p: 1,
        s: 10,
        name: ''
      },
      testcaseList: [],
      environmentList: [],
      variableList: [{
        key: '',
        type: 'string',
        value: ''
      }],
      headerList: [{
        key: '',
        value: ''
      }],
      paramsList: [{
        key: '',
        type: 'string',
        value: ''
      }],
      formDataList: [{
        key: '',
        type: 'string',
        value: ''
      }],
      parametersList: [{
        key: '',
        value: ''
      }],
      extractList: [{
        key: '',
        value: ''
      }],
      assertList: [{
        key: '',
        method: 'equals',
        type: 'string',
        value: ''
      }],
      setupHooksList: [{
        key: ''
      }],
      teardownHooksList: [{
        key: ''
      }],
      tmpKeyValueList: [],
      tmpKeyTypeValueList: [],
      tmpKeyList: [],
      total: 0,
      addTestCaseDialogVisible: false,
      editTestCaseDialogVisible: false,
      runTestCaseDialogVisible: false,
      mainActiveName: 'first',
      activeName: 'one',
      requestBodyName: 'one',
      backName: 'one',
      otherName: 'one',
      allCase: [],
      choiceCase: [],
      runCaseId: '',
      // 选中的前置用例
      rightChoiceCase: [],
      // 公共配置
      configOptions: [],
      choiceConfig: [],
      caseId: '',
      requestMethods: [
        { value: 1, label: 'GET' },
        { value: 2, label: 'POST' },
        { value: 3, label: 'PUT' },
        { value: 4, label: 'DELETE' }
      ],
      dataType: [
        { value: 1, label: 'string' },
        { value: 2, label: 'int' },
        { value: 3, label: 'float' },
        { value: 4, label: 'boolean' }
      ],
      assertType: [
        { value: 1, label: 'equals' },
        { value: 2, label: 'not_equals' },
        { value: 3, label: 'string_equals' },
        { value: 4, label: 'length_equals' },
        { value: 5, label: 'startswith' },
        { value: 6, label: 'endswith' },
        { value: 7, label: 'less_than' },
        { value: 8, label: 'less_than_or_equals' },
        { value: 9, label: 'greater_than' },
        { value: 10, label: 'greater_than_or_equals' },
        { value: 11, label: 'length_greater_than' },
        { value: 12, label: 'length_greater_than_or_equals' },
        { value: 13, label: 'length_less_than' },
        { value: 14, label: 'length_less_than_or_equals' },
        { value: 15, label: 'contains' },
        { value: 16, label: 'contained_by' },
        { value: 17, label: 'type_match' },
        { value: 18, label: 'regex_match' }
      ],
      requestMethod: '',
      requestUrl: '',
      jsonAddData: '',
      jsonEditData: '',
      projectAndInterfaceNames: [],
      setupProjectAndInterfaceNames: [],
      projectAndInterfaceAndConfigNames: [],
      interfaceNames: [],
      setupInterfaceNames: [],
      tmpProjectId: '',
      tmpInterfaceId: '',
      tmpTestCaseList: [],
      stopFlag: false,
      stopConfigFlag: false,
      addTestCaseRule: {
        project_id: [
          { required: true, message: '所属项目不能为空！', trigger: 'blur' }
        ],
        interface_id: [
          { required: true, message: '所属接口不能为空！', trigger: 'blur' }
        ],
        name: [
          { required: true, message: '用例名称不能为空！', trigger: 'blur' },
          { min: 2, max: 50, message: '长度在 2 到 50 个字符！', trigger: 'blur' }
        ]
      },
      editTestCaseRule: {
        project_id: [
          { required: true, message: '所属项目不能为空！', trigger: 'blur' }
        ],
        interface_id: [
          { required: true, message: '所属接口不能为空！', trigger: 'blur' }
        ],
        name: [
          { required: true, message: '用例名称不能为空！', trigger: 'blur' },
          { min: 2, max: 50, message: '长度在 2 到 50 个字符！', trigger: 'blur' }
        ]
      },
      runTestCaseRule: {
        env_id: [
          { required: true, message: '运行环境不能为空！', trigger: 'blur' }
        ]
      }
    }
  },
  methods: {
    // json数据初始化
    jsonDataInit () {
      require('brace/theme/chrome')
      require('brace/ext/language_tools')
      require('brace/mode/json')
      require('brace/snippets/json')
    },
    // 获取用例列表
    getTestCaseList () {
      if (this.queryParams.name !== this.tmpName) {
        this.tmpName = this.queryParams.name
        this.queryParams.p = 1
      }
      getTestCases(this.queryParams)
        .then(response => {
          if (response.data.code !== 0) return this.$message.error('获取测试用例列表失败！')
          this.testcaseList = response.data.data.results
          this.total = response.data.data.count
        })
    },
    // 获取环境名称列表
    getEnvironmentNameList () {
      getEnvironmentNames()
        .then(response => {
          if (response.data.code !== 0) return this.$message.error('获取环境名称列表失败！')
          this.environmentList = response.data.data
        })
    },
    // 打开运行用例对话框
    openRunTestCaseDialog (caseInfo) {
      this.runCaseId = caseInfo.id
      this.getEnvironmentNameList()
      this.runTestCaseDialogVisible = true
    },
    // 运行用例
    runThisTestCase () {
      this.$refs.runTestCaseRef.validate(valid => {
        if (!valid) return
        this.loading = true
        this.runTestCaseDialogVisible = false
        runTestCase(this.runCaseId, this.runTestCaseForm)
          .then(response => {
            if (response.data.code !== 0) {
              this.loading = false
              return this.$message.error(response.data.message.run)
            }
            this.loading = false
            this.$message.success(response.data.message.run)
            this.runCaseId = ''
            this.runTestCaseForm = { env_id: '' }
          })
      })
      this.getTestCaseList()
    },
    // 运行对话框关闭
    runDialogClose () {
      this.$refs.runTestCaseRef.resetFields()
      this.environmentList = []
    },
    // 运行用例对话框关闭
    runTestCaseDialogClose () {
      this.runTestCaseDialogVisible = false
      this.runDialogClose()
      this.runCaseId = ''
      this.runTestCaseForm = {
        env_id: ''
      }
    },
    // 获取项目下测试用例名称列表
    getProjectAndInterfaceNameList () {
      getProjectAndInterfaceNames()
        .then(response => {
          if (response.data.code !== 0) return this.$message.error('获取项目测试用例列表失败！')
          this.projectAndInterfaceNames = response.data.data
          for (const project of this.projectAndInterfaceNames) {
            if (project.id === this.editTestCaseForm.project_id) {
              this.interfaceNames = project.interface
            }
          }
          this.setupProjectAndInterfaceNames = response.data.data
          for (const project of this.setupProjectAndInterfaceNames) {
            if (project.id === this.setupProjectAndInterface.project_id) {
              this.setupInterfaceNames = project.interface
            }
          }
        })
    },
    // 获取项目下公共配置名称列表
    getProjectAndInterfaceAndConfigNames () {
      getProjectAndInterfaceAndConfigNames()
        .then(response => {
          if (response.data.code !== 0) return this.$message.error('获取项目公共配置名称列表失败！')
          this.configOptions = []
          for (const project of response.data.data) {
            this.configOptions.push({
              id: project.id,
              name: project.name,
              config: project.interface
            })
          }
        })
    },
    // 打开创建用例对话框
    openAddTestCaseDialog () {
      this.getProjectAndInterfaceNameList()
      this.getProjectAndInterfaceAndConfigNames()
      this.addTestCaseDialogVisible = true
    },
    // 打开编辑用例对话框
    openEditTestCaseDialog (caseInfo) {
      this.getProjectAndInterfaceNameList()
      this.getProjectAndInterfaceAndConfigNames()
      this.editTestCaseForm = { ...caseInfo }
      this.caseId = this.editTestCaseForm.id
      delete this.editTestCaseForm.id
      delete this.editTestCaseForm.interface
      delete this.editTestCaseForm.project
      delete this.editTestCaseForm.create_time
      this.editTestCaseForm.content = JSON.parse(this.editTestCaseForm.content)
      if (JSON.parse(this.editTestCaseForm.fixture).length !== 0) {
        this.choiceCase = JSON.parse(this.editTestCaseForm.fixture)
        for (const project of this.projectAndInterfaceNames) {
          if (this.stopFlag) break
          this.tmpProjectId = project.id
          for (const interface1 of project.interface) {
            if (this.stopFlag) {
              this.allCase = this.tmpTestCaseList
              break
            }
            this.tmpInterfaceId = interface1.id
            this.tmpTestCaseList = interface1.testcase
            for (const testcase of interface1.testcase) {
              if (this.stopFlag) break
              if (testcase.id === this.choiceCase[0]) {
                this.setupProjectAndInterface.project_id = this.tmpProjectId
                this.setupProjectAndInterface.interface_id = this.tmpInterfaceId
                this.stopFlag = true
              }
            }
          }
        }
      } else {
        this.allCase = []
        this.choiceCase = []
      }
      if (this.editTestCaseForm.config !== null) {
        for (const project of this.configOptions) {
          if (this.stopConfigFlag) break
          this.tmpProjectId = project.id
          for (const interface1 of project.config) {
            if (this.stopConfigFlag) break
            this.tmpInterfaceId = interface1.id
            for (const config of interface1.config) {
              if (this.stopConfigFlag) break
              if (config.id === this.editTestCaseForm.config) {
                this.choiceConfig.push(this.tmpProjectId, this.tmpInterfaceId, this.editTestCaseForm.config)
                this.stopConfigFlag = true
              }
            }
          }
        }
      } else {
        this.choiceConfig = []
      }
      this.requestMethod = this.editTestCaseForm.content.request.method
      this.requestUrl = this.editTestCaseForm.content.request.url
      if (this.editTestCaseForm.content.request.json === undefined) {
        this.jsonEditData = ''
        this.editTestCaseForm.content.request.json = {}
      } else {
        this.jsonEditData = JSON.stringify(this.editTestCaseForm.content.request.json, null, 2)
      }
      if (Object.keys(this.editTestCaseForm.content.variables).length === 0) {
        this.variableList = [{ key: '', type: 'string', value: '' }]
      } else {
        this.variableList = []
        for (const variable of this.editTestCaseForm.content.variables) {
          this.variableList.push({
            key: variable.key,
            type: variable.type,
            value: variable.value
          })
        }
      }
      if (Object.keys(this.editTestCaseForm.content.request.headers).length === 0) {
        this.headerList = [{ key: '', value: '' }]
      } else {
        this.headerList = []
        for (const key in this.editTestCaseForm.content.request.headers) {
          this.headerList.push({
            key: key,
            value: this.editTestCaseForm.content.request.headers[key]
          })
        }
      }
      if (this.editTestCaseForm.content.request.params !== undefined) {
        if (this.editTestCaseForm.content.request.params.length === 0) {
          this.paramsList = [{ key: '', type: 'string', value: '' }]
        } else {
          this.paramsList = []
          for (const params of this.editTestCaseForm.content.request.params) {
            this.paramsList.push({
              key: params.key,
              type: params.type,
              value: params.value
            })
          }
        }
      } else {
        this.editTestCaseForm.content.request.params = []
        this.paramsList = [{ key: '', type: 'string', value: '' }]
      }
      if (this.editTestCaseForm.content.request.data !== undefined) {
        if (this.editTestCaseForm.content.request.data.length === 0) {
          this.formDataList = [{ key: '', type: 'string', value: '' }]
        } else {
          this.formDataList = []
          for (const formData of this.editTestCaseForm.content.request.data) {
            this.formDataList.push({
              key: formData.key,
              type: formData.type,
              value: formData.value
            })
          }
        }
      } else {
        this.editTestCaseForm.content.request.data = []
        this.formDataList = [{ key: '', type: 'string', value: '' }]
      }
      if (Object.keys(this.editTestCaseForm.content.parameters).length === 0) {
        this.parametersList = [{ key: '', value: '' }]
      } else {
        this.parametersList = []
        for (const key in this.editTestCaseForm.content.parameters) {
          this.parametersList.push({
            key: key,
            value: this.editTestCaseForm.content.parameters[key]
          })
        }
      }
      if (Object.keys(this.editTestCaseForm.content.extract).length === 0) {
        this.extractList = [{ key: '', value: '' }]
      } else {
        this.extractList = []
        for (const extract of this.editTestCaseForm.content.extract) {
          this.extractList.push({
            key: Object.keys(extract)[0],
            value: Object.values(extract)[0]
          })
        }
      }
      if (this.editTestCaseForm.content.validate.length === 0) {
        this.assertList = [{ key: '', method: 'equals', type: 'string', value: '' }]
      } else {
        this.assertList = []
        for (const validate of this.editTestCaseForm.content.validate) {
          this.assertList.push({
            key: validate.key,
            method: validate.method,
            type: validate.type,
            value: validate.value
          })
        }
      }
      if (Object.keys(this.editTestCaseForm.content.setupHooks).length === 0) {
        this.setupHooksList = [{ key: '' }]
      } else {
        this.setupHooksList = []
        for (const setupHooks of this.editTestCaseForm.content.setupHooks) {
          this.setupHooksList.push({
            key: setupHooks
          })
        }
      }
      if (Object.keys(this.editTestCaseForm.content.teardownHooks).length === 0) {
        this.teardownHooksList = [{ key: '' }]
      } else {
        this.teardownHooksList = []
        for (const teardownHooks of this.editTestCaseForm.content.teardownHooks) {
          this.teardownHooksList.push({
            key: teardownHooks
          })
        }
      }
      this.editTestCaseDialogVisible = true
    },
    // 创建用例对话框项目改变
    addProjectChange () {
      for (const project of this.projectAndInterfaceNames) {
        if (project.id === this.addTestCaseForm.project_id) {
          this.interfaceNames = project.interface
          if (this.interfaceNames.length > 0) {
            this.addTestCaseForm.interface_id = this.interfaceNames[0].id
          } else {
            this.addTestCaseForm.interface_id = null
          }
        }
      }
    },
    // 编辑用例对话框项目改变
    editProjectChange () {
      for (const project of this.projectAndInterfaceNames) {
        if (project.id === this.editTestCaseForm.project_id) {
          this.interfaceNames = project.interface
          if (this.interfaceNames.length > 0) {
            this.editTestCaseForm.interface_id = this.interfaceNames[0].id
          } else {
            this.editTestCaseForm.interface_id = null
          }
        }
      }
    },
    // 创建前置用例项目改变
    addSetupProjectChange () {
      for (const project of this.setupProjectAndInterfaceNames) {
        if (project.id === this.setupProjectAndInterface.project_id) {
          this.setupInterfaceNames = project.interface
          if (this.setupInterfaceNames.length > 0) {
            this.setupProjectAndInterface.interface_id = this.setupInterfaceNames[0].id
            this.addSetupInterfaceChange()
          } else {
            this.setupProjectAndInterface.interface_id = null
          }
        }
      }
    },
    // 编辑前置用例项目改变
    editSetupProjectChange () {
      for (const project of this.setupProjectAndInterfaceNames) {
        if (project.id === this.setupProjectAndInterface.project_id) {
          this.setupInterfaceNames = project.interface
          if (this.setupInterfaceNames.length > 0) {
            this.setupProjectAndInterface.interface_id = this.setupInterfaceNames[0].id
            this.addSetupInterfaceChange()
          } else {
            this.setupProjectAndInterface.interface_id = null
          }
        }
      }
    },
    // 创建前置用例接口改变
    addSetupInterfaceChange () {
      for (const interface1 of this.setupInterfaceNames) {
        if (interface1.testcase.length > 0) {
          for (const case1 of interface1.testcase) {
            if (case1.id === this.caseId) {
              case1.disabled = true
            }
          }
        }
        if (interface1.id === this.setupProjectAndInterface.interface_id) {
          if (interface1.testcase.length > 0) {
            this.allCase = interface1.testcase
          } else {
            this.allCase = []
          }
        }
      }
    },
    // 编辑前置用例接口改变
    editSetupInterfaceChange () {
      for (const interface1 of this.setupInterfaceNames) {
        if (interface1.id === this.setupProjectAndInterface.interface_id) {
          if (interface1.testcase.length > 0) {
            this.allCase = interface1.testcase
          } else {
            this.allCase = []
          }
        }
      }
    },
    // 记录选中的前置用例
    rightChoiceCaseChange () {
      this.rightChoiceCase = this.choiceCase
    },
    // 新增局部变量表单项
    addVariable () {
      this.variableList.push({
        key: '',
        type: 'string',
        value: ''
      })
    },
    // 删除局部变量表单项
    deleteVariable (item) {
      const index = this.variableList.indexOf(item)
      if (index !== -1 && this.variableList.length > 1) {
        this.variableList.splice(index, 1)
      }
    },
    // 新增请求头表单项
    addHeader () {
      this.headerList.push({
        key: '',
        value: ''
      })
    },
    // 删除请求头表单项
    deleteHeader (item) {
      const index = this.headerList.indexOf(item)
      if (index !== -1 && this.headerList.length > 1) {
        this.headerList.splice(index, 1)
      }
    },
    // 新增查询参数表单项
    addParams () {
      this.paramsList.push({
        key: '',
        type: 'string',
        value: ''
      })
    },
    // 删除查询参数表单项
    deleteParams (item) {
      const index = this.paramsList.indexOf(item)
      if (index !== -1 && this.paramsList.length > 1) {
        this.paramsList.splice(index, 1)
      }
    },
    // 新增表单参数项
    addFormData () {
      this.formDataList.push({
        key: '',
        type: 'string',
        value: ''
      })
    },
    // 删除表单参数项
    deleteFormData (item) {
      const index = this.formDataList.indexOf(item)
      if (index !== -1 && this.formDataList.length > 1) {
        this.formDataList.splice(index, 1)
      }
    },
    // 新增参数化表单项
    addParameters () {
      this.parametersList.push({
        key: '',
        value: ''
      })
    },
    // 删除参数化表单项
    deleteParameters (item) {
      const index = this.parametersList.indexOf(item)
      if (index !== -1 && this.parametersList.length > 1) {
        this.parametersList.splice(index, 1)
      }
    },
    // 新增extract项
    addExtract () {
      this.extractList.push({
        key: '',
        value: ''
      })
    },
    // 删除extract项
    deleteExtract (item) {
      const index = this.extractList.indexOf(item)
      if (index !== -1 && this.extractList.length > 1) {
        this.extractList.splice(index, 1)
      }
    },
    // 新增assert项
    addAssert () {
      this.assertList.push({
        key: '',
        method: 'equals',
        type: 'string',
        value: ''
      })
    },
    // 删除assert项
    deleteAssert (item) {
      const index = this.assertList.indexOf(item)
      if (index !== -1 && this.assertList.length > 1) {
        this.assertList.splice(index, 1)
      }
    },
    // 新增setup_hooks项
    addSetupHook () {
      this.setupHooksList.push({
        key: ''
      })
    },
    // 删除setup_hooks项
    deleteSetupHook (item) {
      const index = this.setupHooksList.indexOf(item)
      if (index !== -1 && this.setupHooksList.length > 1) {
        this.setupHooksList.splice(index, 1)
      }
    },
    // 新增teardown_hooks项
    addTeardownHook () {
      this.teardownHooksList.push({
        key: ''
      })
    },
    // 删除teardown_hooks项
    deleteTeardownHook (item) {
      const index = this.teardownHooksList.indexOf(item)
      if (index !== -1 && this.teardownHooksList.length > 1) {
        this.teardownHooksList.splice(index, 1)
      }
    },
    // 移除多余的空白项
    removeKeyValueBlankItem (type) {
      this.tmpKeyValueList = []
      if (type === 'variable') {
        this.tmpKeyValueList = this.variableList
        this.variableList = []
        for (const variable of this.tmpKeyValueList) {
          if (variable.key !== '') {
            this.variableList.push(variable)
          }
        }
        if (this.variableList.length === 0) {
          this.addVariable()
        }
      }
      if (type === 'header') {
        this.tmpKeyValueList = this.headerList
        this.headerList = []
        for (const header of this.tmpKeyValueList) {
          if (header.key !== '' && header.value !== '') {
            this.headerList.push(header)
          }
        }
        if (this.headerList.length === 0) {
          this.addHeader()
        }
      }
      if (type === 'params') {
        this.tmpKeyValueList = this.paramsList
        this.paramsList = []
        for (const params of this.tmpKeyValueList) {
          if (params.key !== '') {
            this.paramsList.push(params)
          }
        }
        if (this.paramsList.length === 0) {
          this.addParams()
        }
      }
      if (type === 'formData') {
        this.tmpKeyValueList = this.formDataList
        this.formDataList = []
        for (const formData of this.tmpKeyValueList) {
          if (formData.key !== '') {
            this.formDataList.push(formData)
          }
        }
        if (this.formDataList.length === 0) {
          this.addFormData()
        }
      }
      if (type === 'parameters') {
        this.tmpKeyValueList = this.parametersList
        this.parametersList = []
        for (const parameters of this.tmpKeyValueList) {
          if (parameters.key !== '') {
            this.parametersList.push(parameters)
          }
        }
        if (this.parametersList.length === 0) {
          this.addParameters()
        }
      }
      if (type === 'extract') {
        this.tmpKeyValueList = this.extractList
        this.extractList = []
        for (const extract of this.tmpKeyValueList) {
          if (extract.key !== '') {
            this.extractList.push(extract)
          }
        }
        if (this.extractList.length === 0) {
          this.addExtract()
        }
      }
      if (type === 'assert') {
        this.tmpKeyTypeValueList = this.assertList
        this.assertList = []
        for (const assert of this.tmpKeyTypeValueList) {
          if (assert.key !== '') {
            this.assertList.push(assert)
          }
        }
        if (this.assertList.length === 0) {
          this.addAssert()
        }
      }
      if (type === 'setupHooks') {
        this.tmpKeyList = this.setupHooksList
        this.setupHooksList = []
        for (const setupHooks of this.tmpKeyList) {
          if (setupHooks.key !== '') {
            this.setupHooksList.push(setupHooks)
          }
        }
        if (this.setupHooksList.length === 0) {
          this.addSetupHook()
        }
      }
      if (type === 'teardownHooks') {
        this.tmpKeyList = this.teardownHooksList
        this.teardownHooksList = []
        for (const teardownHooks of this.tmpKeyList) {
          if (teardownHooks.key !== '') {
            this.teardownHooksList.push(teardownHooks)
          }
        }
        if (this.teardownHooksList.length === 0) {
          this.addTeardownHook()
        }
      }
    },
    // 创建用例
    addTestCase () {
      // 组装用例
      this.removeKeyValueBlankItem('variable')
      if (this.variableList.length === 1 && this.variableList[0].key === '' && this.variableList[0].value === '') {
        this.addTestCaseForm.content.variables = []
      } else {
        this.addTestCaseForm.content.variables = this.variableList
      }
      this.removeKeyValueBlankItem('header')
      if (this.headerList.length === 1 && this.headerList[0].key === '' && this.headerList[0].value === '') {
        this.addTestCaseForm.content.request.headers = {}
      } else {
        this.addTestCaseForm.content.request.headers = {}
        for (const header of this.headerList) {
          this.addTestCaseForm.content.request.headers[header.key] = header.value
        }
      }
      this.removeKeyValueBlankItem('params')
      if (this.paramsList.length === 1 && this.paramsList[0].key === '' && this.paramsList[0].value === '') {
        this.addTestCaseForm.content.request.params = []
      } else {
        this.addTestCaseForm.content.request.params = this.paramsList
      }
      this.removeKeyValueBlankItem('formData')
      if (this.formDataList.length === 1 && this.formDataList[0].key === '' && this.formDataList[0].value === '') {
        this.addTestCaseForm.content.request.data = []
      } else {
        this.addTestCaseForm.content.request.data = this.formDataList
      }
      this.removeKeyValueBlankItem('parameters')
      if (this.parametersList.length === 1 && this.parametersList[0].key === '' && this.parametersList[0].value === '') {
        this.addTestCaseForm.content.parameters = {}
      } else {
        this.addTestCaseForm.content.parameters = {}
        for (const parameters of this.parametersList) {
          this.addTestCaseForm.content.parameters[parameters.key] = parameters.value
        }
      }
      this.removeKeyValueBlankItem('extract')
      if (this.extractList.length === 1 && this.extractList[0].key === '' && this.extractList[0].value === '') {
        this.addTestCaseForm.content.extract = []
      } else {
        this.addTestCaseForm.content.extract = []
        for (const extract of this.extractList) {
          this.tmpDict = {}
          this.tmpDict[extract.key] = extract.value
          this.addTestCaseForm.content.extract.push(this.tmpDict)
        }
      }
      this.removeKeyValueBlankItem('assert')
      if (this.assertList.length === 1 && this.assertList[0].key === '' && this.assertList[0].value === '') {
        this.addTestCaseForm.content.validate = []
      } else {
        this.addTestCaseForm.content.validate = this.assertList
      }
      this.removeKeyValueBlankItem('setupHooks')
      if (this.setupHooksList.length === 1 && this.setupHooksList[0].key === '') {
        this.addTestCaseForm.content.setupHooks = []
      } else {
        this.addTestCaseForm.content.setupHooks = []
        for (const setupHooks of this.setupHooksList) {
          this.addTestCaseForm.content.setupHooks.push(setupHooks.key)
        }
      }
      this.removeKeyValueBlankItem('teardownHooks')
      if (this.teardownHooksList.length === 1 && this.teardownHooksList[0].key === '') {
        this.addTestCaseForm.content.teardownHooks = []
      } else {
        this.addTestCaseForm.content.teardownHooks = []
        for (const teardownHooks of this.teardownHooksList) {
          this.addTestCaseForm.content.teardownHooks.push(teardownHooks.key)
        }
      }
      if (this.choiceConfig.length === 3) {
        this.addTestCaseForm.config = Number(this.choiceConfig.pop())
      } else {
        this.addTestCaseForm.config = null
      }
      if (this.rightChoiceCase) {
        this.addTestCaseForm.fixture = '[' + String(this.rightChoiceCase) + ']'
      }
      if (this.jsonAddData !== '') {
        this.addTestCaseForm.content.request.json = JSON.parse(this.jsonAddData)
      }
      this.addTestCaseForm.content.request.method = this.requestMethod
      this.addTestCaseForm.content.request.url = this.requestUrl
      if (this.requestMethod === '' || this.requestMethod === 'DELETE') {
        delete this.addTestCaseForm.content.request.params
        delete this.addTestCaseForm.content.request.data
        delete this.addTestCaseForm.content.request.json
      } else if (this.requestMethod === 'GET') {
        delete this.addTestCaseForm.content.request.data
        delete this.addTestCaseForm.content.request.json
        if (Object.keys(this.addTestCaseForm.content.request.params).length === 0) {
          delete this.addTestCaseForm.content.request.params
        }
      } else if (this.requestMethod === 'POST' || this.requestMethod === 'PUT') {
        delete this.addTestCaseForm.content.request.params
        if (Object.keys(this.addTestCaseForm.content.request.json).length === 0 && Object.keys(this.addTestCaseForm.content.request.data).length === 0) {
          delete this.addTestCaseForm.content.request.data
          delete this.addTestCaseForm.content.request.json
        } else if (Object.keys(this.addTestCaseForm.content.request.json).length !== 0 && Object.keys(this.addTestCaseForm.content.request.data).length === 0) {
          delete this.addTestCaseForm.content.request.data
        } else if (Object.keys(this.addTestCaseForm.content.request.data).length !== 0 && Object.keys(this.addTestCaseForm.content.request.json).length === 0) {
          delete this.addTestCaseForm.content.request.json
        }
      }
      this.addTestCaseForm.content = JSON.stringify(this.addTestCaseForm.content)
      this.$refs.addTestCaseRef.validate(valid => {
        if (!valid) return
        createTestCase(this.addTestCaseForm)
          .then(response => {
            if (response.data.code !== 0) return this.$message.error('创建测试用例失败！')
            this.$message.success('创建测试用例成功！')
            this.addTestCaseDialogClose()
            this.getTestCaseList()
          })
      })
    },
    // 编辑用例
    editTestCase () {
      // 组装用例
      this.removeKeyValueBlankItem('variable')
      if (this.variableList.length === 1 && this.variableList[0].key === '' && this.variableList[0].value === '') {
        this.editTestCaseForm.content.variables = []
      } else {
        this.editTestCaseForm.content.variables = this.variableList
      }
      this.removeKeyValueBlankItem('header')
      if (this.headerList.length === 1 && this.headerList[0].key === '' && this.headerList[0].value === '') {
        this.editTestCaseForm.content.request.headers = {}
      } else {
        this.editTestCaseForm.content.request.headers = {}
        for (const header of this.headerList) {
          this.editTestCaseForm.content.request.headers[header.key] = header.value
        }
      }
      this.removeKeyValueBlankItem('params')
      if (this.paramsList.length === 1 && this.paramsList[0].key === '' && this.paramsList[0].value === '') {
        this.editTestCaseForm.content.request.params = []
      } else {
        this.editTestCaseForm.content.request.params = this.paramsList
      }
      this.removeKeyValueBlankItem('formData')
      if (this.formDataList.length === 1 && this.formDataList[0].key === '' && this.formDataList[0].value === '') {
        this.editTestCaseForm.content.request.data = []
      } else {
        this.editTestCaseForm.content.request.data = this.formDataList
      }
      this.removeKeyValueBlankItem('parameters')
      if (this.parametersList.length === 1 && this.parametersList[0].key === '' && this.parametersList[0].value === '') {
        this.editTestCaseForm.content.parameters = {}
      } else {
        this.editTestCaseForm.content.parameters = {}
        for (const parameters of this.parametersList) {
          this.editTestCaseForm.content.parameters[parameters.key] = parameters.value
        }
      }
      this.removeKeyValueBlankItem('extract')
      if (this.extractList.length === 1 && this.extractList[0].key === '' && this.extractList[0].value === '') {
        this.editTestCaseForm.content.extract = []
      } else {
        this.editTestCaseForm.content.extract = []
        for (const extract of this.extractList) {
          this.tmpDict = {}
          this.tmpDict[extract.key] = extract.value
          this.editTestCaseForm.content.extract.push(this.tmpDict)
        }
      }
      this.removeKeyValueBlankItem('assert')
      if (this.assertList.length === 1 && this.assertList[0].key === '' && this.assertList[0].value === '') {
        this.editTestCaseForm.content.validate = []
      } else {
        this.editTestCaseForm.content.validate = this.assertList
      }
      this.removeKeyValueBlankItem('setupHooks')
      if (this.setupHooksList.length === 1 && this.setupHooksList[0].key === '') {
        this.editTestCaseForm.content.setupHooks = []
      } else {
        this.editTestCaseForm.content.setupHooks = []
        for (const setupHooks of this.setupHooksList) {
          this.editTestCaseForm.content.setupHooks.push(setupHooks.key)
        }
      }
      this.removeKeyValueBlankItem('teardownHooks')
      if (this.teardownHooksList.length === 1 && this.teardownHooksList[0].key === '') {
        this.editTestCaseForm.content.teardownHooks = []
      } else {
        this.editTestCaseForm.content.teardownHooks = []
        for (const teardownHooks of this.teardownHooksList) {
          this.editTestCaseForm.content.teardownHooks.push(teardownHooks.key)
        }
      }
      if (this.choiceConfig.length === 3) {
        this.editTestCaseForm.config = Number(this.choiceConfig.pop())
      } else {
        this.editTestCaseForm.config = null
      }
      if (this.rightChoiceCase) {
        this.editTestCaseForm.fixture = '[' + String(this.rightChoiceCase) + ']'
      }
      if (this.jsonEditData !== '') {
        this.editTestCaseForm.content.request.json = JSON.parse(this.jsonEditData)
      } else {
        this.editTestCaseForm.content.request.json = {}
      }
      this.editTestCaseForm.content.request.method = this.requestMethod
      this.editTestCaseForm.content.request.url = this.requestUrl
      if (this.requestMethod === '' || this.requestMethod === 'DELETE') {
        delete this.editTestCaseForm.content.request.params
        delete this.editTestCaseForm.content.request.data
        delete this.editTestCaseForm.content.request.json
      } else if (this.requestMethod === 'GET') {
        delete this.editTestCaseForm.content.request.data
        delete this.editTestCaseForm.content.request.json
        if (this.editTestCaseForm.content.request.params.length === 0) {
          delete this.editTestCaseForm.content.request.params
        }
      } else if (this.requestMethod === 'POST' || this.requestMethod === 'PUT') {
        delete this.editTestCaseForm.content.request.params
        if (Object.keys(this.editTestCaseForm.content.request.json).length === 0 && this.editTestCaseForm.content.request.data.length === 0) {
          delete this.editTestCaseForm.content.request.data
          delete this.editTestCaseForm.content.request.json
        } else if (Object.keys(this.editTestCaseForm.content.request.json).length !== 0 && this.editTestCaseForm.content.request.data.length === 0) {
          delete this.editTestCaseForm.content.request.data
        } else if (this.editTestCaseForm.content.request.data.length !== 0 && Object.keys(this.editTestCaseForm.content.request.json).length === 0) {
          delete this.editTestCaseForm.content.request.json
        }
      }
      this.editTestCaseForm.content = JSON.stringify(this.editTestCaseForm.content)
      this.$refs.editTestCaseRef.validate(valid => {
        if (!valid) return
        editTestCase(this.caseId, this.editTestCaseForm)
          .then(response => {
            if (response.data.code !== 0) return this.$message.error('编辑测试用例失败！')
            this.$message.success('编辑测试用例成功！')
            this.editTestCaseDialogClose()
            this.getTestCaseList()
          })
      })
      this.editTestCaseDialogClose()
    },
    // 创建对话框关闭
    addDialogClose () {
      this.$refs.addTestCaseRef.resetFields()
      this.variableList = [{ key: '', type: 'string', value: '' }]
      this.headerList = [{ key: '', value: '' }]
      this.paramsList = [{ key: '', type: 'string', value: '' }]
      this.formDataList = [{ key: '', type: 'string', value: '' }]
      this.parametersList = [{ key: '', value: '' }]
      this.extractList = [{ key: '', value: '' }]
      this.assertList = [{ key: '', method: 'equals', type: 'string', value: '' }]
      this.setupHooksList = [{ key: '' }]
      this.teardownHooksList = [{ key: '' }]
      this.choiceConfig = []
      this.mainActiveName = 'first'
      this.activeName = 'one'
      this.requestBodyName = 'one'
      this.backName = 'one'
      this.otherName = 'one'
      this.requestMethod = ''
      this.requestUrl = ''
      this.addTestCaseForm = {
        project_id: '',
        interface_id: '',
        name: '',
        config: null,
        fixture: [],
        content: {
          request: {
            url: '',
            method: '',
            headers: {},
            json: {},
            data: [],
            params: []
          },
          parameters: {},
          variables: {},
          extract: [],
          validate: [],
          setupHooks: [],
          teardownHooks: []
        }
      }
      this.allCase = []
      this.choiceCase = []
      this.rightChoiceCase = []
      this.jsonAddData = ''
      this.setupProjectAndInterface = { project_id: '', interface_id: '' }
    },
    // 编辑对话框关闭
    editDialogClose () {
      this.$refs.editTestCaseRef.resetFields()
      this.variableList = [{ key: '', type: 'string', value: '' }]
      this.headerList = [{ key: '', value: '' }]
      this.paramsList = [{ key: '', type: 'string', value: '' }]
      this.formDataList = [{ key: '', type: 'string', value: '' }]
      this.parametersList = [{ key: '', value: '' }]
      this.extractList = [{ key: '', value: '' }]
      this.assertList = [{ key: '', method: 'equals', type: 'string', value: '' }]
      this.setupHooksList = [{ key: '' }]
      this.teardownHooksList = [{ key: '' }]
      this.mainActiveName = 'first'
      this.activeName = 'one'
      this.requestBodyName = 'one'
      this.backName = 'one'
      this.otherName = 'one'
      this.tmpProjectId = ''
      this.tmpInterfaceId = ''
      this.tmpTestCaseList = []
      this.stopFlag = false
      this.stopConfigFlag = false
      this.choiceConfig = []
      this.requestMethod = ''
      this.requestUrl = ''
      this.allCase = []
      this.choiceCase = []
      this.rightChoiceCase = []
      this.jsonEditData = ''
      this.setupProjectAndInterface = { project_id: '', interface_id: '' }
    },
    // 创建用例对话框关闭
    addTestCaseDialogClose () {
      this.addTestCaseDialogVisible = false
      this.addDialogClose()
    },
    // 编辑用例对话框关闭
    editTestCaseDialogClose () {
      this.editTestCaseDialogVisible = false
      this.editDialogClose()
    },
    // 删除用例
    deleteThisTestCase (testcaseId) {
      this.$confirm('此操作将永久删除该测试用例, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        deleteTestCase(testcaseId).then(response => {
          if (response.data.code !== 0) return this.$message.error('删除测试用例失败！')
          this.$message.success('删除测试用例成功！')
          this.total -= 1
          if (this.total === (this.queryParams.p - 1) * this.queryParams.s && this.total !== 0) {
            this.queryParams.p -= 1
          }
          this.getTestCaseList()
        })
      }).catch(err => err)
    },
    // 监听size变化
    handleSizeChange (newSize) {
      this.queryParams.s = newSize
      this.getTestCaseList()
    },
    // 监听页码变化
    handleCurrentChange (newPage) {
      this.queryParams.p = newPage
      this.getTestCaseList()
    },
    handleTabPage (tab, event) {
      return 0
    },
    // 表格样式
    cellStyle (data) {
      if (data.column.label === '用例名称') {
        return 'color: #409EFF'
      }
    }
  }
}
</script>

<style lang="less" scoped>
  .el-row {
    margin-top: 10px;
    padding-left: 20px;
    font-size: 12px
  }
  .el-tabs{
    margin-top: 15px;
    font-size: 12px
  }
  /deep/ .el-tabs__item {
    font-size: 12px;
  }
  /deep/ .el-dialog__body {
    padding: 20px 35px 10px 20px;
  }
  /deep/ .el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label {
    font-size: 12px;
    color: #303133;
    font-weight: 400;
  }
  /deep/ .el-transfer-panel {
    width: 240px;
  }
  /deep/ .el-transfer__buttons {
    padding: 0 10px;
  }
  /deep/ .el-transfer__buttons .el-button{
    padding: 5px 10px;
  }
</style>
